/* Simple TCP SYN Denial Of Service                                      */
/* Author: Luis Martin Garcia. luis.martingarcia [.at.] gmail [d0t] com  */
/* To compile: gcc tcpsyndos.c -o tcpsyndos -lpcap                       */
/* Run as root!                                                          */
/*                                                                       */
/* This code is distributed under the GPL License. For more info check:  */
/* http://www.gnu.org/copyleft/gpl.html                                  */


#define __USE_BSD         /* Using BSD IP header           */ 
#include <netinet/ip.h>   /* Internet Protocol             */ 
#define __FAVOR_BSD       /* Using BSD TCP header          */ 
#include <netinet/tcp.h>  /* Transmission Control Protocol */ 
#include <pcap.h>         /* Libpcap                       */ 
#include <string.h>       /* String operations             */ 
#include <stdlib.h>       /* Standard library definitions  */ 
#include<linux/if_ether.h>
#define TCPSYN_LEN 20
#define MAXBYTES2CAPTURE 2048
#define MAC_FMT  "\t%02x:%02x:%02x:%02x:%02x:%02x" 
#define STREAM fp
#define ETHHDROFFSET 0
#define IPHDROFFSET		(sizeof(struct ethhdr)+ETHHDROFFSET)
#define TCPHDROFFSET	(IPHDROFFSET+sizeof(struct ip))
#define UDPHDROFFSET	(IPHDROFFSET+sizeof(struct ip))
#define APPHDROFFSET_BASE_TCP	(TCPHDROFFSET+sizeof(struct tcphdr))
#define APPHDROFFSET_BASE_UDP	(UDPHDROFFSET+sizeof(struct udphdr))
#define FILTERCOMMEND "ether proto /ip"//"port 80"
typedef unsigned short u_int16;
typedef unsigned long u_int32;


/* main(): Main function. Opens network interface for capture. Tells the kernel*/
/* to deliver packets with the ACK or PSH-ACK flags set. Prints information    */
/* about captured packets. Calls TCP_RST_send() to kill the TCP connection     */
/* using TCP RST packets.                                                      */
int main(int argc, char *argv[] ){
 
	int count=0;
	bpf_u_int32 netaddr=0, mask=0;    /* To Store network address and netmask   */ 
	struct bpf_program filter;        /* Place to store the BPF filter program  */ 
	char errbuf[PCAP_ERRBUF_SIZE];    /* Error buffer                           */ 
	pcap_t *descr = NULL;             /* Network interface handler              */ 
	struct pcap_pkthdr pkthdr;        /* Packet information (timestamp,size...) */ 
	const unsigned char *packet=NULL; /* Received raw data                      */
	struct ethhdr *etherhdr = NULL;/* Enternet Header				*/
	struct ip *iphdr = NULL;          /* IPv4 Header                            */
	struct tcphdr *tcphdr = NULL;     /* TCP Header                             */
	memset(errbuf,0,PCAP_ERRBUF_SIZE);
	
	/* open a file to write*/
	FILE *fp = fopen("./1.pcap","a+");
	if(fp==NULL)
	{
		fprintf(stderr,"open file failed!\n");
		return -1;
	}
   
	if (argc != 2){
		fprintf(stderr, "USAGE: tcpsyndos <interface>\n");
		exit(1);
	}

 	/* Open network device for packet capture */ 
	descr = pcap_open_live(argv[1], MAXBYTES2CAPTURE, 1,  0, errbuf);
	if(descr==NULL){
		fprintf(stderr, "pcap_open_live(): %s \n", errbuf);
		exit(1);
	}

 	/* Look up info from the capture device. */ 
	if ( pcap_lookupnet( argv[1] , &netaddr, &mask, errbuf) == -1 ){ 
		fprintf(stderr, "ERROR: pcap_lookupnet(): %s\n", errbuf );
		exit(1);
	}
#if 1
 	/* Compiles the filter expression into a BPF filter program */
	if ( pcap_compile(descr, &filter, "port 5060", 1, mask) == -1){
		fprintf(stderr, "Error in pcap_compile(): %s\n", pcap_geterr(descr) );
		exit(1);	
	}
 
 	/* Load the filter program into the packet capture device. */ 
	if( pcap_setfilter(descr,&filter) == -1 ){
		fprintf(stderr, "Error in pcap_setfilter(): %s\n", pcap_geterr(descr));
		exit(1);
	}
	
	#endif
	
	while(1){ 
			/* Get one packet */
		if ( (packet = pcap_next(descr,&pkthdr)) == NULL){
			fprintf(stderr, "Error in pcap_next():%s\n", errbuf);
			exit(1);
			continue;	
	}

	etherhdr = (struct ethhdr*)packet;
	iphdr = (struct ip *)(packet+sizeof(struct ethhdr));
	tcphdr = (struct tcphdr *)(packet+sizeof(struct ethhdr)+sizeof(struct ip));
	if(count==0)fprintf(STREAM,"+-------------------------+\n");
	fprintf(STREAM,"Received Packet No.%d:\n", ++count);
	
	/* display the enternet header */
	fprintf(STREAM,"ethernet header:\n");
	fprintf(STREAM,"Destination:");
	fprintf(STREAM,MAC_FMT,etherhdr->h_dest[0],etherhdr->h_dest[1],etherhdr->h_dest[2],etherhdr->h_dest[3],etherhdr->h_dest[4],etherhdr->h_dest[5]);
	fprintf(STREAM,"\n");
	fprintf(STREAM,"Source:");
	fprintf(STREAM,MAC_FMT,etherhdr->h_source[0],etherhdr->h_source[1],etherhdr->h_source[2],etherhdr->h_source[3],etherhdr->h_source[4],etherhdr->h_source[5]);
	fprintf(STREAM,"\n");
	fprintf(STREAM,"\tType:0x%x\n",ntohs(etherhdr->h_proto));
	
	/* display the IP header */
	fprintf(STREAM,"IP header:\n");
	fprintf(STREAM,"\tVersion:%d\n\tHeader size:%d\n\tSource:%s\n\tDestination:%s\n",iphdr->ip_v,iphdr->ip_hl,inet_ntoa(iphdr->ip_src),inet_ntoa(iphdr->ip_dst));
	fprintf(STREAM,"\tTotal Length:%d\n",ntohs(iphdr->ip_len)*4);	//totallenght = ip_len * 4, 32bit * 5 = 160bit, 160bit = 20
	fprintf(STREAM,"\tIdentification:0x%x\n",ntohs(iphdr->ip_id));
	fprintf(STREAM,"\tFragment offset:%d\n",ntohs(iphdr->ip_off));
	fprintf(STREAM,"\tTime to live:%u\n",ntohs(iphdr->ip_ttl));
	fprintf(STREAM,"\tProtocol:%u\n",ntohs(iphdr->ip_p));
	fprintf(STREAM,"\tChecknum:0x%x\n",ntohs(iphdr->ip_sum));
	
	/* display the transport header */
	fprintf(STREAM,"transport header:\n");
	fprintf(STREAM,"\tSource Port:%d\n",ntohs(tcphdr->th_sport));
	fprintf(STREAM,"\tDestination Port:%d\n",ntohs(tcphdr->th_dport));
	fprintf(STREAM,"\tSequeuece number:%u\n",ntohs(tcphdr->th_seq));
	fprintf(STREAM,"\tAck:%u\n",ntohl(tcphdr->th_ack));
	fprintf(STREAM,"\tWindow:%u\n",ntohs(tcphdr->th_win));
	fprintf(STREAM,"\tChecksum:%u\n",ntohs(tcphdr->th_sum));
	fprintf(STREAM,"\tUrgent pointer:%u\n",ntohs(tcphdr->th_urp));
	
	/* display the http or sip line and header */
	fprintf(STREAM,"http or sip line and header:\n");
	packet+=APPHDROFFSET_BASE_TCP;
	char *tmp;
	tmp = strstr((char*)packet,"HTTP");
	if(tmp==NULL) 
		tmp = strstr((char*)packet,"SIP");
	if(tmp==NULL)
		continue;
	packet = (u_char*)tmp;
	//tmp = strstr((char*)packet,"Content-Length:");
	if(tmp!=NULL){
		tmp = strstr((char*)tmp,"\t\n\t\n");
		if(tmp){
			for(int i=0;i<4;i++)
				*(tmp+i)=0;
		}		
	}
#if 0
	char *puserData = NULL;//strstr((char*)packet,"\t\n\t\n");
	if(puserData==NULL)
	{
		fprintf(STREAM,"\tAPP header is NULL!\n");
		continue;
	}
	*puserData='\0';
	puserData+=4;
#endif
#if 0
	for(char *p_line=(char*)packet;;){
		if(p_line[0]=='\r'&&p_line[1]=='\n')
			break;
		packet = (u_char*)p_line;
		p_line = strstr(p_line,"\r\n");
		if(p_line==NULL)
			continue;
		*p_line='\0';
		p_line+=2;
		fprintf(STREAM,"%s\n",packet);
	}
#else	
	fprintf(STREAM,"%s\n",packet);
#endif
 	fprintf(STREAM,"+-------------------------+\n");
} 

return 0;

}

